#include "EventApplication.h"

#include "EventAddWindow.h"
#include "EventClient.h"
#include "EventWindow.h"
#include "EventItem.h"

#include <object_v2/object_v2-type.h>

struct _EventApplication
{
        AdwApplication parent_instance;

        /*主窗口*/
        GtkWindow   *window;

        EventClient *client;

        /*本地是否包含用户信息*/
        gboolean is_pulled_local_file;
};

G_DEFINE_FINAL_TYPE(EventApplication, event_application, ADW_TYPE_APPLICATION)

EventApplication *
event_application_new(const gchar *application_id, GApplicationFlags flags)
{
        return g_object_new(EVENT_TYPE_APPLICATION,
                            "application-id",
                            application_id,
                            "flags",
                            flags,
                            NULL);
}

static void
apply_buffer(GtkWidget *widget, gpointer data)
{
        GtkEntryBuffer  **buffer     = (GtkEntryBuffer **)data;
        EventApplication *self       = (EventApplication *)buffer[4];
        GtkWindow        *top_window = (GtkWindow *)buffer[5];

        const char       *user_class, *user_name, *user_password;

        user_class    = gtk_entry_buffer_get_text(buffer[0]);
        user_name     = gtk_entry_buffer_get_text(buffer[1]);
        user_password = gtk_entry_buffer_get_text(buffer[2]);

        event_client_set_user_info(self->client,
                                   user_class,
                                   user_name,
                                   user_password);

        gtk_window_destroy((GtkWindow *)buffer[3]);

        ObjectString *response;
        response = event_client_send_request(self->client,
                                             EVENT_REQUEST_TYPE_QUERY);

        if (!response) {
                OBJECT_ERROR_TOOL(EventApplication, apply_buffer, "空响应！\n");
                return;
        }

        event_window_takle_with_response(EVENT_WINDOW(top_window), response);
        object_unref(response);
}

static void
create_user_info(GtkWindow *top_window, EventApplication *app)
{
        GtkWindow *create_user_info_window = GTK_WINDOW(gtk_window_new());
        GtkWidget *grid, *labels[3], *entrys[3], *button;
        static GtkEntryBuffer *buffer[6];

        gtk_window_set_title(create_user_info_window, "新建用户信息");
        gtk_window_set_default_size(create_user_info_window, 200, 160);

        grid      = gtk_grid_new();
        labels[0] = gtk_label_new("班级");
        labels[1] = gtk_label_new("姓名");
        labels[2] = gtk_label_new("密码");
        button    = gtk_button_new_with_label("确认");
        for (int i = 0; i < 3; ++i) {
                buffer[i] = gtk_entry_buffer_new(NULL, -1);
                entrys[i] = gtk_entry_new_with_buffer(buffer[i]);
        }

        for (int i = 0; i < 3; ++i) {
                gtk_grid_attach(GTK_GRID(grid), labels[i], 0, i, 1, 1);
                gtk_grid_attach(GTK_GRID(grid), entrys[i], 1, i, 1, 1);
        }

        gtk_grid_attach(GTK_GRID(grid), button, 1, 3, 1, 1);
        buffer[3] = (GtkEntryBuffer *)create_user_info_window;
        buffer[4] = (GtkEntryBuffer *)app;
        buffer[5] = (GtkEntryBuffer *)top_window;

        g_signal_connect(button,
                         "clicked",
                         G_CALLBACK(apply_buffer),
                         (gpointer)buffer);

        gtk_window_set_child(create_user_info_window, grid);

        gtk_window_present(create_user_info_window);
}

/**
 * 从服务端查询事件条目，并显示在窗口中
 */
static void
query_from_client(EventApplication *self)
{
        ObjectString *response;

        response = event_client_send_request(self->client,
                                             EVENT_REQUEST_TYPE_QUERY);

        if (!response) {
                OBJECT_ERROR_TOOL(EventApplication, activate, "空响应！\n");
                return;
        }

        event_window_takle_with_response(EVENT_WINDOW(self->window), response);
        object_unref(response);
}

static void
activate(GApplication *app)
{
        EventApplication *self = EVENT_APPLICATION(app);

        g_assert(EVENT_IS_APPLICATION(app));

        self->window = gtk_application_get_active_window(GTK_APPLICATION(app));

        if (!self->window) {
                self->window = g_object_new(EVENT_TYPE_WINDOW,
                                            "application",
                                            app,
                                            NULL);
        }

        gtk_window_present(self->window);

        if (!self->is_pulled_local_file) {
                create_user_info(self->window, self);
                return;
        }

        query_from_client(self);
}

static void
event_application_finalize(GObject *object)
{
        EventApplication *self = EVENT_APPLICATION(object);

        g_object_unref(self->client);

        G_OBJECT_CLASS(event_application_parent_class)->finalize(object);

        OBJECT_INFO_TOOL(EventApplication, finalize, "已清理\n");
}

static void
event_application_class_init(EventApplicationClass *klass)
{
        GObjectClass      *object_class = G_OBJECT_CLASS(klass);
        GApplicationClass *app_class    = G_APPLICATION_CLASS(klass);

        object_class->finalize          = event_application_finalize;
        app_class->activate             = activate;
}

static void
about_action(GSimpleAction *action, GVariant *parameter, gpointer user_data)
{
        static const char *authors[] = {"korack/咸鱼雨涵", NULL};
        EventApplication  *self      = user_data;
        GtkWindow         *window    = NULL;

        g_assert(EVENT_IS_APPLICATION(self));

        window = gtk_application_get_active_window(GTK_APPLICATION(self));

        adw_show_about_dialog(GTK_WIDGET(window),
                              "application-name",
                              GETTEXT_PACKAGE,
                              "developers",
                              authors,
                              "application-icon",
                              "EventAndTask",
                              "version",
                              PACKAGE_VERSION,
                              "copyright",
                              "© 2023 korack/咸鱼雨涵",
                              NULL);
}

static void
add_event(EventApplication *self, EventAddWindow *add_window)
{
        const char   *event_date, *event_name, *event_content;
        ObjectString *response;

        if (!event_add_window_can_get_info(add_window))
                return;

        event_date    = event_add_window_get_event_date(add_window);
        event_name    = event_add_window_get_event_name(add_window);
        event_content = event_add_window_get_event_content(add_window);

        event_client_set_request_option(self->client,
                                        event_date,
                                        event_name,
                                        event_content);
        response = event_client_send_request(self->client,
                                             EVENT_REQUEST_TYPE_INSERT);

        if (!response) {
                OBJECT_WARNING_TOOL(EventApplication,
                                    add_event,
                                    "未获取到返回信息！\n");
                return;
        }

        ObjectStringApplication *tokens, *tmp[2];

        tokens = object_string_application_new_with(response->charset);
        object_string_application_set_segment_charset(tokens, '&');
        object_string_application_rewind(tokens);
        tmp[0] = object_string_application_get_string_before_segment(tokens);
        tmp[1] = object_string_application_get_string_before_segment(tokens);

        g_print("[%s]: %s\n",
                object_string_get_string(OBJECT_STRING(tmp[0])),
                object_string_get_string(OBJECT_STRING(tmp[1])));

        object_unref(tmp[0]);
        object_unref(tmp[1]);
        object_unref(response);
        object_unref(tokens);

        query_from_client(self);
}

static void
add_event_action(GSimpleAction *action, GVariant *parameter, gpointer self)
{
        EventAddWindow *add_window = event_add_window_new();

        g_signal_connect_swapped(add_window,
                                 "close-request",
                                 G_CALLBACK(add_event),
                                 self);

        gtk_window_present(GTK_WINDOW(add_window));
}

static void
item_remove_action(GSimpleAction *action, GVariant *parameter, gpointer data)
{
        
        g_print("#debug.1, <%b>\n", EVENT_IS_ITEM(data));
}

static const GActionEntry app_actions[] = {
        {      "about",       about_action},
        {  "add-event",   add_event_action},
        {"item-remove", item_remove_action},
};

static void
event_application_init(EventApplication *self)
{
        g_action_map_add_action_entries(G_ACTION_MAP(self),
                                        app_actions,
                                        G_N_ELEMENTS(app_actions),
                                        self);

        self->client = event_client_new();
        self->is_pulled_local_file =
                event_client_read_local_user_info(self->client);
}
